import maya.cmds  as mc
import maya.mel as mel

import LZ_public_command.LZ_UI
reload(LZ_public_command.LZ_UI)

import LZ_public_command.LZ_controllar_command
reload( LZ_public_command.LZ_controllar_command )

import LZ_public_command.LZ_rename_command
reload( LZ_public_command.LZ_rename_command)

import LZ_public_command.LZ_general_command
reload(LZ_public_command.LZ_general_command)

import LZ_public_command.LZ_rivet
reload(LZ_public_command.LZ_rivet)

import LZ_public_command.LZ_skinCluster
reload(LZ_public_command.LZ_skinCluster)

import LZ_public_command.LZ_blendshape_command
reload(LZ_public_command.LZ_blendshape_command)

import LZ_public_command.LZ_sdk_command
reload(LZ_public_command.LZ_sdk_command)

import LZ_public_command.LZ_Attribute
reload(LZ_public_command.LZ_Attribute)



class deformer_manager(LZ_public_command.LZ_controllar_command.LZ_controllar_command , 
                            LZ_public_command.LZ_UI.LZ_UI,
                            LZ_public_command.LZ_rename_command.rename_commands ,
                            LZ_public_command.LZ_general_command.general_command ,
                            LZ_public_command.LZ_rivet.LZ_rivetClass ,
                            LZ_public_command.LZ_skinCluster.LZ_skinCluster,
                            LZ_public_command.LZ_blendshape_command.LZ_blendshape_command,
                            LZ_public_command.LZ_sdk_command.LZ_sdk_command,
                            LZ_public_command.LZ_Attribute.LZ_attribute
                            ):
    def __init__(self):
        pass
        
    def deformer_manager_UI(self):
        deformer_manager_UI = 'deformer_manager_UI'
        if mc.window(deformer_manager_UI,ex = True):
            mc.deleteUI(deformer_manager_UI)
            
        mc.window(deformer_manager_UI,widthHeight=(450, 400),t = deformer_manager_UI,menuBar = True,rtf=True,s=True)

        main = mc.columnLayout('mdlar_SDK_main',columnAttach=('both', 5), rowSpacing=10, columnWidth=450 )
        
        split_BS_frame = mc.frameLayout( 'splitBS_frameLY',label='BS_split_mdlar', borderStyle='in',collapsable=False,bgc =(0.1,0.1,0.1) ,font = 'boldLabelFont')
        
        mc.rowLayout( 'splitBS01_rowLY',numberOfColumns=3,columnWidth3=(100, 250,100), adjustableColumn=3, columnAlign=(1, 'right'), columnAttach=[(1, 'both', 0), (2, 'both', 0), (2, 'both', 0)])
        
        mc.text(   ' orgMesh : '  )
        mc.textField( 'load_OrgMesh_textField',text='' )
        mc.button( 'load_splitBS_orgMesh' , l = 'load' , c =  lambda *args:self.loadTextField( 'load_OrgMesh_textField' ) )
        
        mc.setParent(split_BS_frame)
        
        mc.rowLayout( 'splitBS02_rowLY',numberOfColumns=3,columnWidth3=(100, 250,100), adjustableColumn=3, columnAlign=(1, 'right'), columnAttach=[(1, 'both', 0), (2, 'both', 0), (2, 'both', 0)])
        
        mc.text(   ' BS_Mesh : '  )
        mc.textField( 'load_BS_Mesh_textField',text='' )
        mc.button( 'load_splitBS_BS_Mesh' , l = 'load' , c =  lambda *args:self.loadTextField( 'load_BS_Mesh_textField' ) )
        
        mc.setParent(split_BS_frame)
        
        mc.rowLayout( 'splitBS03_rowLY',numberOfColumns=3,columnWidth3=(100, 250,100), adjustableColumn=3, columnAlign=(1, 'right'), columnAttach=[(1, 'both', 0), (2, 'both', 0), (2, 'both', 0)])
        
        mc.text(   ' skin_Mesh : '  )
        mc.textField( 'load_skin_Mesh_textField',text='' )
        mc.button( 'load_splitBS_skin_Mesh' , l = 'load' , c =  lambda *args:self.loadTextField( 'load_skin_Mesh_textField' ) )
        
        mc.setParent(split_BS_frame)
        mc.button('splitBS_bt' , l = 'modify' , c = lambda *args:self.splitBS_for_UI() )
        
        mc.setParent(main)
        mc.separator( style='none' )
        
        mirrorDeformer_frame = mc.frameLayout( 'mirrorDeformer_frameLY',label='mirrorDeformer_mdlar', borderStyle='in',collapsable=False,bgc =(0.1,0.1,0.1) ,font = 'boldLabelFont')
        
        mc.rowLayout( 'mirrorDeformer01_rowLY',numberOfColumns=3,columnWidth3=(100, 250,100), adjustableColumn=3, columnAlign=(1, 'right'), columnAttach=[(1, 'both', 0), (2, 'both', 0), (2, 'both', 0)])
        
        mc.text(   ' orgMesh : '  )
        mc.textField( 'load_deformerMesh_textField',text='' )
        mc.button( 'load_splitBS_orgMesh' , l = 'load' , c =  lambda *args:self.loadTextField( 'load_deformerMesh_textField' ) )
        
        mc.setParent(mirrorDeformer_frame)
        
        mc.rowLayout( 'mirrorDeformer02_rowLY',numberOfColumns=3,columnWidth3=(100, 250,100), adjustableColumn=3, columnAlign=(1, 'right'), columnAttach=[(1, 'both', 0), (2, 'both', 0), (2, 'both', 0)])
        mc.text(   ' inputDeformer : '  )
        mc.textField( 'load_inputDeformer_textField',text='' )
        mc.button( 'load_inputDeformer_orgMesh' , l = 'load' , c =  lambda *args:self.loadTextField( 'load_inputDeformer_textField' ) )
        
        mc.setParent(mirrorDeformer_frame)
        
        mc.rowLayout( 'mirrorDeformer03_rowLY',numberOfColumns=3,columnWidth3=(100, 250,100), adjustableColumn=3, columnAlign=(1, 'right'), columnAttach=[(1, 'both', 0), (2, 'both', 0), (2, 'both', 0)])
        mc.text(   ' mirrorDeformer : '  )
        mc.textField( 'load_mirrorDeformer_textField',text='' )
        mc.button( 'load_mirrorDeformer_orgMesh' , l = 'load' , c =  lambda *args:self.loadTextField( 'load_mirrorDeformer_textField' ) )
        
        mc.setParent(mirrorDeformer_frame)
        
        mc.rowLayout( 'mirrorDeformer04_rowLY',numberOfColumns=4,columnWidth4=(100, 80,80,10), adjustableColumn=4, columnAlign=(1, 'right'), columnAttach=[(1, 'both', 0), (2, 'both', 0), (2, 'both', 0), (2, 'both', 0)])
        mc.text(   ' mirrorAxis : '  )
        mc.optionMenu( 'posneg_menu' , label='  ' ,w=60)
        
        mc.menuItem( label='+' )
        mc.menuItem( label='-' )
        
        mc.optionMenu( 'axis_menu' , label='  ',w=100 )
        
        mc.menuItem( label='X' )
        mc.menuItem( label='Y' )
        mc.menuItem( label='Z' )
        
        
        mc.setParent(mirrorDeformer_frame)
        mc.button('mirrorDeformer_bt' , l = 'modify' , c = lambda *args:self.mirrorDeformer_forUI() )
                
        mc.showWindow(deformer_manager_UI)
        
        
    ###===================================================================================================================
    
    def splitBS_for_UI(self):
        
        bsMesh = mc.textField( 'load_BS_Mesh_textField',q = True , text = True )
        orgMesh = mc.textField( 'load_OrgMesh_textField',q = True , text = True )
        skinmesh = mc.textField( 'load_skin_Mesh_textField',q = True , text = True )
        
        skinNode = self.listSkinCluster( inputMesh = skinmesh )

        jnts = self.listAllSkined_joints( skinClus = skinNode)
        
        self.splitBlendshape( inputBSMesh = bsMesh , orgMesh = orgMesh ,skinMesh = skinmesh , jointInput = jnts )
    
    
    def mirrorDeformer_forUI(self):
        
        deformerMesh = mc.textField( 'load_deformerMesh_textField',q=True , text= True )
        deformer_input = mc.textField( 'load_inputDeformer_textField',q=True , text= True )
        deformer_mirror = mc.textField( 'load_mirrorDeformer_textField',q=True , text= True )
        
        posneg = mc.optionMenu( 'posneg_menu' , q = True ,v = True)
        Axis = mc.optionMenu( 'axis_menu' , q = True ,v = True)
        
        if posneg == '+':
            posneg_value = 0
        else:
            posneg_value = 1
            
        if deformer_input == deformer_mirror:
            lonly = 1
        else:
            lonly = 0
                        
        self.mirrorDerformerWeight(  inputMesh = deformerMesh , inputDerformer = deformer_input , mirrorDeformer = deformer_mirror , mirrorAxis = Axis , ifRverse = posneg_value , ifLonly = lonly )
                    
    def mirrorDerformerWeight(self , inputMesh = '' , inputDerformer = '' , mirrorDeformer = '' , mirrorAxis = 'X' , ifRverse = 0 , ifLonly = 0 ):
        
        meshTemple = str(inputMesh) + '_mirrorTemple'
        mc.duplicate( inputMesh , n = meshTemple ) 
        
        baseJnt = str(inputMesh)+ '_templeBaseJnt'
        mc.select(cl=True)
        mc.joint( n =baseJnt )
        
        if ifLonly == 0:
            
            targetMesh = str(inputMesh) + '_mirrorMesh'
            mc.duplicate( inputMesh , n = targetMesh ) 
            mc.setAttr(str(targetMesh)+'.scaleX',lock=False)
            mc.setAttr(str(targetMesh)+'.scaleX',-1)
            
            L_mirrorJnt = 'L_' + str(inputMesh)+ '_templeJnt'
            
            R_mirrorJnt = 'R_' + str(inputMesh)+ '_templeJnt'
            
            mc.select(cl=True)
            mc.joint( n =L_mirrorJnt )
            
            mc.select(cl=True)
            mc.joint( n =R_mirrorJnt )
            
            if mirrorAxis == 'X':
                mc.setAttr( str(L_mirrorJnt)+'.translateX' , 1 )
                mc.setAttr( str(R_mirrorJnt)+'.translateX' , 1 )
                
            elif mirrorAxis == 'Y':
                mc.setAttr( str(L_mirrorJnt)+'.translateY' , 1 )
                mc.setAttr( str(R_mirrorJnt)+'.translateY' , 1 )
            else  :
                mc.setAttr( str(L_mirrorJnt)+'.translateZ' , 1 )
                mc.setAttr( str(R_mirrorJnt)+'.translateZ' , 1 )
            
            
            skinInfo = mc.skinCluster( baseJnt, meshTemple ,normalizeWeights =3  )
            
            targetskinInfo = mc.skinCluster( baseJnt, targetMesh ,normalizeWeights = 3  )
            
            

            mc.skinCluster( skinInfo[0] , e = True , ug = True , dr = 5 , ps =  0 , ns = 10 , lw = True , wt = 0 , ai =  [L_mirrorJnt  ])
            
            mc.skinCluster( targetskinInfo[0] , e = True , ug = True , dr = 5 , ps =  0 , ns = 10 , lw = True , wt = 0 , ai =  [ R_mirrorJnt ])

            mc.setAttr(str(skinInfo[0])+ '.envelope' , 0 )
            mc.setAttr(str(targetskinInfo[0])+ '.envelope' , 0 )
            #if ifRverse == 0 :
            #    orgJnt= L_mirrorJnt
            #    targetJnt = R_mirrorJnt
            #else:
            #    orgJnt= R_mirrorJnt
            #    targetJnt = L_mirrorJnt
            #
            
            self.deformer_2_skin(  skinNode = skinInfo[0] , skinMesh = meshTemple , wireMesh = inputMesh ,infJoint = L_mirrorJnt , deformerNode = inputDerformer )

            #if mirrorAxis == 'X':
            #    mAxis = 'YZ'
            #elif mirrorAxis == 'Y':
            #    mAxis = 'XZ'
            #else  :
            #    mAxis = 'XY'
            
            mc.copySkinWeights( ss = skinInfo[0] , ds = targetskinInfo[0] ,surfaceAssociation = 'closestPoint' ,influenceAssociation = 'closestJoint' ,noMirror =True )
            
            #mc.select(meshTemple)           
            #if  ifRverse == 0 :
            #    mel.eval( ' doMirrorSkinWeightsArgList( 2, { " -mirrorMode ' + mAxis + ' -surfaceAssociation closestPoint -influenceAssociation closestJoint" } );copySkinWeights -ss '+ skinInfo[0] + ' -ds ' +skinInfo[0]  + ' -mirrorMode ' +  mAxis +' -surfaceAssociation closestPoint -influenceAssociation closestJoint; ')
            #else:
            #    mel.eval( ' doMirrorSkinWeightsArgList( 2, { " -mirrorMode ' + mAxis + ' -mirrorInverse -surfaceAssociation closestPoint -influenceAssociation closestJoint" } );copySkinWeights -ss '+ skinInfo[0] + ' -ds ' +skinInfo[0]  + ' -mirrorMode ' +  mAxis +' -surfaceAssociation closestPoint -influenceAssociation closestJoint; ')
 
            self.setSkinValue_2_deformer_OnMesh(  skinNode = targetskinInfo[0]  , skinMesh = targetMesh , wireMesh = inputMesh , infJoint = R_mirrorJnt , deformerNode = mirrorDeformer )
            

            mc.delete(meshTemple,baseJnt,L_mirrorJnt,R_mirrorJnt)
        else:
            mirrorJnt =   str(inputMesh)+ '_templeJnt'
            
            mc.select(cl=True)
            mc.joint( n = mirrorJnt )
            
            mc.setAttr(str(mirrorJnt)+'.translateY' , 1)
            
            skinInfo = mc.skinCluster( baseJnt, meshTemple ,normalizeWeights =3 )
            mc.setAttr(str(skinInfo[0])+ '.skinningMethod' , 2 )
            mc.skinCluster( skinInfo[0] , e = True , ug = True , dr = 5 , ps =  0 , ns = 10 , lw = True , wt = 0 , ai =  [mirrorJnt] )
            mc.setAttr(str(skinInfo[0])+ '.envelope' , 0 )
            self.deformer_2_skin(  skinNode = skinInfo[0] , skinMesh = meshTemple , wireMesh = inputMesh ,infJoint = mirrorJnt , deformerNode = inputDerformer )
            
            if mirrorAxis == 'X':
                mAxis = 'YZ'
            elif mirrorAxis == 'Y':
                mAxis = 'XZ'
            else  :
                mAxis = 'XY'
            
            
            mc.copySkinWeights( ss = skinInfo[0] , ds = skinInfo[0]  , mirrorInverse =True , mirrorMode = mAxis )
 
            #mc.select(meshTemple)  
            
            #if  ifRverse == 0 :
            #    mel.eval( ' doMirrorSkinWeightsArgList( 2, { " -mirrorMode ' + mAxis + ' -surfaceAssociation closestPoint -influenceAssociation closestJoint" } );copySkinWeights -ss '+ skinInfo[0] + ' -ds ' +skinInfo[0]  + ' -mirrorMode ' +  mAxis +' -surfaceAssociation closestPoint -influenceAssociation closestJoint; ')
            #else:
            #    mel.eval( ' doMirrorSkinWeightsArgList( 2, { " -mirrorMode ' + mAxis + ' -mirrorInverse -surfaceAssociation closestPoint -influenceAssociation closestJoint" } );copySkinWeights -ss '+ skinInfo[0] + ' -ds ' +skinInfo[0]  + ' -mirrorMode ' +  mAxis +' -surfaceAssociation closestPoint -influenceAssociation closestJoint; ')
            self.setSkinValue_2_deformer_OnMesh(  skinNode = skinInfo[0]  , skinMesh = meshTemple , wireMesh = inputMesh , infJoint = mirrorJnt , deformerNode = mirrorDeformer )
            
            mc.delete( mirrorJnt , baseJnt , meshTemple )
        
            
    ### ==================================================================================================================
    def getinputWireDeformer(self , inputMesh = '' ):
        inputHistory = mc.listHistory(inputMesh , lv =1 )
        wire_all = []
        for ih in inputHistory:
            if mc.nodeType(ih) == 'wire':
                wire_all.append(ih)
        
        return wire_all
        
        
    def setSkinValue_2_deformer_OnMesh( self , skinNode = '' , skinMesh = '' , wireMesh = '' ,infJoint = '', deformerNode = '' ):
    
        polyPoints = mc.polyEvaluate( skinMesh  ,v=True)
        for i in range(polyPoints) :
            infJnt = mc.skinPercent(skinNode,'%s.vtx[%s]' %(skinMesh,i),query=True,t=None) #per model inf joint list
            jntWet = mc.skinPercent(skinNode,'%s.vtx[%s]' %(skinMesh,i),query=True,v=True) #per joint weight
            
            num = 0
            for inj in infJnt:
                if inj == infJoint:
                    weight = jntWet[num]
                    mc.percent( deformerNode ,str(wireMesh)+'.vtx[' +str(i)+']' , v = weight ) 


                else:
                    pass
                num = num+1
        

    def deformer_2_skin( self , skinNode = '' , skinMesh = '' , wireMesh = '' ,infJoint = '', deformerNode = '' ):
        polyPoints = mc.polyEvaluate( wireMesh  ,v=True)
        for i in range(polyPoints):
            weight = mc.percent( deformerNode ,str(wireMesh)+'.vtx[' +str(i)+']' , q=True ,v = True ) 
            
            mc.skinPercent(skinNode,'%s.vtx[%s]' %(skinMesh,i),tv = (infJoint, weight[0] ))#per model inf joint list  
            
    ### ==================================================================================================================      
    def splitBlendshape(self,inputBSMesh = '' , orgMesh = '' ,skinMesh = '' , jointInput = [''] ):
        
        mountVertex = mc.polyEvaluate( orgMesh ,vertex =True)
        
        skinClusterNode = self.listSkinCluster( inputMesh = skinMesh )
        
        
        
        if skinClusterNode == None :
            return None
            
        else:
            #pSphere2.vtx[277]
            for jnt  in jointInput:
            
                jnts = mc.skinCluster( skinClusterNode , q = True , influence = True )
                
                if jnt in jnts:
                    newMesh = str(skinMesh) +'_' +str(jnt)
                    mc.duplicate( orgMesh , n = newMesh )
                    
                    for i in range(mountVertex):
                        
                        value = mc.skinPercent( skinClusterNode , str(skinMesh) + '.vtx[' + str(i)+ ']', ignoreBelow = 0.00001 , transform = jnt ,  query=True, value = True )
                        
                        position_org = mc.xform( str( orgMesh ) + '.vtx[' + str(i)+ ']' , q=True, t=True , objectSpace = True)
                        position_BS = mc.xform( str( inputBSMesh ) + '.vtx[' + str(i)+ ']' , q=True, t=True , objectSpace = True)
                        
                        position = [ position_BS[0]*value + position_org[0]*(1-value) , position_BS[1]*value + position_org[1]*(1-value)  , position_BS[2]*value + position_org[2]*(1-value)  ]
                        
                        mc.xform( str( newMesh ) + '.vtx[' + str(i)+ ']' , t = position )